home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / mint104s.zoo / mint.src / dosmem.c < prev    next >
C/C++ Source or Header  |  1993-03-08  |  34KB  |  1,287 lines

  1. /*
  2. Copyright 1990,1991,1992 Eric R. Smith.
  3. Copyright 1992 Atari Corporation.
  4. All rights reserved.
  5. */
  6.  
  7. /*
  8.  * GEMDOS emulation routines: these are for the GEMDOS system calls
  9.  * concerning allocating/freeing memory, including Pexec() (since
  10.  * this allocates memory) and Pterm() (since this, implicitly, frees
  11.  * it).
  12.  */
  13.  
  14. #include "mint.h"
  15.  
  16. int procdate, proctime;    /* set when any processes are created/destroyed */
  17.  
  18. static long do_vfork P_((int));
  19.  
  20. /*
  21.  * new call for TT TOS, for the user to inform DOS of alternate memory
  22.  * FIXME: we really shouldn't trust the user so completely
  23.  * FIXME: doesn't work if memory protection is on
  24.  */
  25.  
  26. long ARGS_ON_STACK
  27. m_addalt(start, size)
  28.     long start, size;
  29. {
  30.     extern int no_mem_prot;        /* see main.c and memprot.c */
  31.  
  32.     if (!no_mem_prot) return 0;    /* pretend to succeed */
  33.     if (!add_region(alt, start, size, M_ALT))
  34.         return EINTRN;
  35.     else
  36.         return 0;
  37. }
  38.  
  39. /*
  40.  * internal routine for doing Malloc on a particular memory map
  41.  */
  42.  
  43. long
  44. _do_malloc(map, size, mode)
  45.     MMAP map;
  46.     long size;
  47.     int mode;
  48. {
  49.     virtaddr v;
  50.     MEMREGION *m;
  51.     long maxsize, mleft;
  52.  
  53.     if (size == -1L) {
  54.         maxsize = max_rsize(map);
  55.         if (curproc->maxmem) {
  56.             mleft = curproc->maxmem - memused(curproc);
  57.             if (maxsize > mleft)
  58.                 maxsize = mleft;
  59.             if (maxsize < 0)
  60.                 maxsize = 0;
  61.         }
  62.     /* make sure to round down */
  63.         return maxsize & ~MASKBITS;
  64.     }
  65.  
  66. /* special case: Malloc(0) should always return 0 */
  67.     if (size == 0)
  68.         return 0;
  69.  
  70.     if (curproc->maxmem) {        /* memory limit? */
  71.         if (size > curproc->maxmem - memused(curproc)) {
  72.             DEBUG(("malloc: memory request would exceed limit"));
  73.             return 0;
  74.         }
  75.     }
  76.  
  77.     m = get_region(map, size, mode);
  78.     if (!m) {
  79.         return 0;
  80.     }
  81.     v = attach_region(curproc, m);
  82.     if (!v) {
  83.         m->links = 0;
  84.         free_region(m);
  85.         return 0;
  86.     }
  87. /* NOTE: get_region returns a region with link count 1; since attach_region
  88.  * increments the link count, we have to remember to decrement the count
  89.  * to correct for this.
  90.  */
  91.     m->links--;
  92.     if ((mode & F_KEEP)) {    /* request for permanent memory */
  93.         m->mflags |= M_KEEP;
  94.     }
  95.     return (long)v;
  96. }
  97.  
  98. long ARGS_ON_STACK
  99. m_xalloc(size, mode)
  100.     long size;
  101.     int mode;
  102. {
  103.     long r, r1;
  104.     int protmode;
  105. #ifndef NO_DEBUG_INFO
  106.     int origmode = mode;
  107. #endif
  108.  
  109.     TRACE(("Mxalloc(%ld,%x)",size,mode));
  110.  
  111. /*
  112.  * AKP: Hack here: if the calling process' PC is in ROM, then this is a
  113.  * Malloc call made by VDI's v_opnvwk routine.  So we change mode to
  114.  * include "super accessible."  This is temporary, until VDI catches up
  115.  * with multitasking TOS.
  116.  */
  117.  
  118.     if (((mode & F_PROTMODE) == 0) &&
  119.         (curproc->ctxt[SYSCALL].pc > 0x00e00000L) &&
  120.         (curproc->ctxt[SYSCALL].pc < 0x00efffffL)) {
  121.         mode |= (F_PROT_S + 0x10) | F_KEEP;
  122.         TRACE(("m_xalloc: VDI special (call from ROM)"));
  123.     }
  124. /*
  125.  * If the mode argument comes in a zero, then set it to the default
  126.  * value from prgflags.  Otherwise subtract one from it to bring it
  127.  * into line with the actual argument to alloc_region.
  128.  */
  129.     protmode = (mode & F_PROTMODE) >> F_PROTSHIFT;
  130.  
  131.     if (protmode == 0) {
  132.         protmode = (curproc->memflags & F_PROTMODE) >> F_PROTSHIFT;
  133.     }
  134.     else --protmode;
  135.  
  136. #if 0
  137. /* I'm very suspicious of the 0x08 flag; I can't see how it could
  138.  * work as the comment below seems to indicate -- ERS
  139.  */
  140.  
  141. /*
  142.  * if the mode argument has the 0x08 bit set then you're trying to change
  143.  * the protection mode of a block you already own. "size" is really its
  144.  * base address. (new as of 2/6/92)
  145.  */
  146.     if (mode & 0x08) change_prot_status(curproc,size,protmode);
  147. #endif
  148.  
  149.     /*
  150.      * Copy the F_KEEP attribute into protmode.  We didn't do that
  151.      * before now because change_prot_status don't want to see no
  152.      * steenking nofree attributes.
  153.      */
  154.  
  155.     protmode |= (mode & F_KEEP);
  156.  
  157.     /* mask off all but the ST/alternative RAM bits before further use */
  158.     mode &= 3;
  159.  
  160.     if (mode == 0) {
  161.         r = _do_malloc(core, size, protmode);
  162.         goto ret;
  163.     }
  164.     else if (mode == 1) {
  165.         r = _do_malloc(alt, size, protmode);
  166.         goto ret;
  167.     }
  168.     else if (size == -1) {
  169.         /* modes 2 and 3 are the same for for size -1 */
  170.         r = _do_malloc(core, -1L, PROT_P);
  171.         r1 = _do_malloc(alt, -1L, PROT_P);
  172.         if (r1 > r) r = r1;
  173.         goto ret;
  174.     }
  175.     else if (mode == 2) {
  176.         r = _do_malloc(core, size, protmode);
  177.         if (r == 0) r = _do_malloc(alt, size, protmode);
  178.         goto ret;
  179.     }
  180.     else /* if (mode == 3) */ {
  181.         r = _do_malloc(alt, size, protmode);
  182.         if (r == 0) r = _do_malloc(core, size, protmode);
  183.         goto ret;
  184.     }
  185. ret:
  186.     if (r == 0) {
  187.         DEBUG(("m_xalloc(%lx,%x) returns 0",size,origmode));
  188.     } else {
  189.         TRACE(("m_xalloc(%lx,%x) returns %lx",size,origmode,r));
  190.     }
  191.     return r;
  192. }
  193.  
  194. long ARGS_ON_STACK
  195. m_alloc(size)
  196.     long size;
  197. {
  198.     long r;
  199.  
  200.     TRACE(("Malloc(%lx)", size));
  201.     if (curproc->memflags & F_ALTALLOC)
  202.         r = m_xalloc(size, 3);
  203.     else
  204.         r = m_xalloc(size, 0);
  205.     TRACE(("Malloc: returning %lx", r));
  206.     return r;
  207. }
  208.  
  209. long ARGS_ON_STACK
  210. m_free(block)
  211.     virtaddr block;
  212. {
  213.     MEMREGION *m;
  214.     int i;
  215.  
  216.     TRACE(("Mfree(%lx)", block));
  217.     if (!block) {
  218.         DEBUG(("Mfree: null pointer"));
  219.         return EIMBA;
  220.     }
  221.  
  222. /* search backwards so that most recently allocated incarnations of
  223.    shared memory blocks are freed first (this doesn't matter very often)
  224.  */
  225.  
  226.     for (i = curproc->num_reg - 1; i >= 0; i--) {
  227.         if (curproc->addr[i] == block) {
  228.             m = curproc->mem[i];
  229.             assert(m != NULL);
  230.             assert(m->loc == (long)block);
  231.             curproc->mem[i] = 0;
  232.             curproc->addr[i] = 0;
  233.             m->links--;
  234.             if (m->links == 0) {
  235.                 free_region(m);
  236.             }
  237.             return 0;
  238.         }
  239.     }
  240.  
  241. /* hmmm... if we didn't find the region, perhaps it's a global
  242.  * one (with the M_KEEP flag set) belonging to a process that
  243.  * terminated
  244.  */
  245.     for (i = rootproc->num_reg - 1; i >= 0; i--) {
  246.         if (rootproc->addr[i] == block) {
  247.             m = rootproc->mem[i];
  248.             assert(m != NULL);
  249.             assert(m->loc == (long)block);
  250.             if (!(m->mflags & M_KEEP))
  251.                 continue;
  252.             TRACE(("Freeing M_KEPT memory"));
  253.             rootproc->mem[i] = 0;
  254.             rootproc->addr[i] = 0;
  255.             m->links--;
  256.             if (m->links == 0) {
  257.                 free_region(m);
  258.             }
  259.             return 0;
  260.         }
  261.     }
  262.  
  263.  
  264.     DEBUG(("Mfree: bad address %lx", block));
  265.     return EIMBA;
  266. }
  267.  
  268. long ARGS_ON_STACK
  269. m_shrink(dummy, block, size)
  270.     int dummy;
  271.     virtaddr block;
  272.     long size;
  273. {
  274.     MEMREGION *m;
  275.     int i;
  276.  
  277.     UNUSED(dummy);
  278.     TRACE(("Mshrink: %lx to %ld", block, size));
  279.     if (!block) {
  280.         DEBUG(("Mshrink: null pointer"));
  281.         return EIMBA;
  282.     }
  283.  
  284.     for (i = 0; i < curproc->num_reg; i++) {
  285.         if (curproc->addr[i] == block) {
  286.             m = curproc->mem[i];
  287.             assert(m != NULL);
  288.             assert(m->loc == (long)block);
  289.             return shrink_region(m, size);
  290.         }
  291.     }
  292.     DEBUG(("Mshrink: bad address (%lx)", block));
  293.     return EIMBA;
  294. }
  295.  
  296. long ARGS_ON_STACK
  297. p_exec(mode, ptr1, ptr2, ptr3)
  298.     int mode;
  299.     void *ptr1, *ptr2, *ptr3;
  300. {
  301.     MEMREGION *base,
  302.         *env = 0;    /* assignment suppresses spurious warning */
  303.     MEMREGION *text = 0;    /* for shared text regions */
  304.     PROC *p;
  305.     long r, flags = 0;
  306.     int i;
  307.     char mkbase = 0, mkload = 0, mkgo = 0, mkwait = 0, mkfree = 0;
  308.     char overlay = 0;
  309.     char thread = 0;
  310.     char ptrace;
  311.     char mkname = 0, *newname, *lastslash;
  312.     char localname[PNAMSIZ+1];
  313.     XATTR xattr;
  314.     int newpid;
  315.  
  316. /* tfmt and tail_offs are used for debugging only */
  317.     const char *tfmt = "Pexec(%d,%s,\"%s\",%lx)";
  318.     int tail_offs = 1;
  319.  
  320. /* the high bit of mode controls process tracing */
  321.     switch(mode & 0x7fff) {
  322.     case 0:
  323.         mkwait = 1;        /* fall through */
  324.     case 100:
  325.         mkload = mkgo = mkfree = 1;
  326.         mkname = 1;
  327.         break;
  328.     case 200:            /* overlay current process */
  329.         mkload = mkgo = 1;
  330.         overlay = mkname = 1;
  331.         break;
  332.     case 3:
  333.         mkload = 1;
  334.         break;
  335.     case 6:
  336.         mkfree = 1;
  337.         /* fall through */
  338.     case 4:
  339.         mkwait = mkgo = 1;
  340.         tfmt = "Pexec(%d,%lx,BP:%lx,%lx)";
  341.         tail_offs = 0;
  342.         break;
  343.     case 106:
  344.         mkfree = 1;        /* fall through */
  345.     case 104:
  346.         thread = (mode == 104);
  347.         mkgo = 1;
  348.         mkname = (ptr1 != 0);
  349.         tfmt = "Pexec(%d,%s,BP:%lx,%lx)";
  350.         tail_offs = 0;
  351.         break;
  352.     case 206:
  353. #if 0
  354.     /* mkfree has no effect when overlay is set, since
  355.      * in this case the "parent" and "child" are the same
  356.      * process; since the "child" will ru